# 为了在命令行使用时调用脚本时使用第三方库
import sys

# sys.path.append("D:/Study/ProgrammingProject/PycharmProject/WangGuan/201230_MEC_PYTHON/venv/Lib/site-packages")
sys.path.append("./venv/Lib/site-packages")
import numpy as np
import matplotlib.pyplot as plt

# 4*4一共16个区域
SIZE = 4

# 回归局部系数
K = 2.7


# 将序号映射到坐标点上
def mapValueToPoint(pointValue):
    pointX = int(pointValue % SIZE)
    if pointX != 0:
        pointY = int(pointValue / SIZE) + 1
    else:
        pointX = SIZE
        pointY = int(pointValue / SIZE)
    return np.array([pointX, pointY])


# 找出起点终点之间经过的区域
def findCoveringPoints(start, end):
    x1 = start[0]
    y1 = start[1]
    x2 = end[0]
    y2 = end[1]
    coveringList = []

    # 计算最终的经过路径
    # 当起点终点在一个区域
    if int(x1) == int(x2) and int(y1) == int(y2):
        coveringList.append(start)
    # 当起点终点不在一个区域
    else:
        # 当x方向更长
        if abs(x1 - x2) > abs(y1 - y2):
            # 获取斜率和截距(x到y方向)
            k = (y2 - y1) / (x2 - x1)
            b = y1 - k * x1
            xLabels = np.array([x1, x2])
            xSort = np.sort(xLabels)
            for oneX in range(xSort[0], xSort[1] + 1):
                onePoint = np.array([oneX, round(k * oneX + b)]).astype(np.int)
                coveringList.append(onePoint)
            # 将输出顺序调整为起点到终点
            if x1 - x2 > 0:
                coveringList.reverse()
        # 当y方向更长
        else:
            # 获取斜率和截距(y到x方向)
            k_inv = (x2 - x1) / (y2 - y1)
            b_inv = x1 - k_inv * y1
            yLabels = np.array([y1, y2])
            ySort = np.sort(yLabels)
            for oneY in range(ySort[0], ySort[1] + 1):
                onePoint = np.array([round(k_inv * oneY + b_inv), oneY]).astype(np.int)
                coveringList.append(onePoint)
            # 将输出顺序调整为起点到终点
            if y1 - y2 > 0:
                coveringList.reverse()
    return np.array(coveringList)


# 读取文件
# xArr (偏移量x0，横坐标x1)
# yArr (纵坐标)
def loadDataSet(fileName):
    dataMat = np.loadtxt(fileName, delimiter=' ', dtype=int)
    xArr = np.zeros((dataMat.shape[0], 2)).astype(np.int16)
    yArr = np.array([])
    xArr[:, 0] = 1
    xArr[:, 1] = dataMat[:, 0]
    yArr = dataMat[:, 1]
    return xArr, yArr


# 对于一个给定的点进行拟合
def lwlr(testPoint, xArr, yArr, k):
    xMat = np.mat(xArr)
    yMat = np.mat(yArr)
    yMat = np.transpose(yMat)
    # 创建对角矩阵
    weights = np.mat(np.eye(xMat.shape[0]))
    # 计算权重矩阵weights
    for i in range(weights.shape[0]):
        diffMat = testPoint - xMat[i, :]
        weights[i, i] = np.exp(diffMat * (np.transpose(diffMat)) / (-2 * k ** 2))
    xTx = np.transpose(xMat) * (weights * xMat)
    # 计算回归系数向量ws----2*1向量(w0,w1)
    ws = np.linalg.inv(xTx) * (np.transpose(xMat) * (weights * yMat))
    # 得到testpoint(x0,x1)的预测结果----x0w0+x1w1=w0+w1*x1
    return testPoint * ws


def lwlrAll(testArr, xArr, yArr, k):
    yHat = np.zeros(np.shape(testArr)[0])
    for i in range(np.shape(testArr)[0]):
        yHat[i] = lwlr(testArr[i], xArr, yArr, k)
    return yHat.astype(np.int16)


# 根据车流量确认拥堵系数
def congestionCoefficient(congestionNum):
    minCong=10000
    maxCong=30000
    minCoef=1
    maxCoef=3
    coefficient=minCoef
    if congestionNum<minCong:
        coefficient=minCoef
    elif congestionNum>maxCong:
        coefficient=maxCoef
    else:
        coefficient=minCoef+(maxCoef-minCoef)*(congestionNum-minCong)/(maxCong-minCong)
    return coefficient


# 输入起点区域和终点区域得到系数
def getCoefficientProcess(start,end):
    # 接住起点和终点
    pointStart = mapValueToPoint(start)
    pointEnd = mapValueToPoint(end)
    # print("Start:", pointStart)
    # print("End:", pointEnd)
    coveringArr = findCoveringPoints(pointStart, pointEnd)
    # print("----经过的坐标----")
    # print(coveringArr)
    coveringPointIdList = []
    for onePoint in coveringArr:
        coveringPointIdList.append((onePoint[1] - 1) * 4 + onePoint[0])
    # print("----经过的点----")
    # print(coveringPointIdList)
    coveringCongestionList = []
    for oneId in coveringPointIdList:
        # 必须用绝对路径
        xArr, yArr = loadDataSet(
            'D:/Study/ProgrammingProject/PycharmProject/191208_FinalProject/processed_datasets/region' + str(
                oneId) + '.txt')
        # xArr [[1 1] [1 2] [1 3]...[1 19]]
        # yArr [12806  9659  9423  8931 10920 12670 12299  9199 10354  8783  9705 11321 14185 15174  9822  8766  8722  8809 14041]
        # 获取一个区域的车流量
        oneIdCongestion = lwlr([1, len(xArr) + 1], xArr, yArr, K)[0, 0]
        coveringCongestionList.append(int(oneIdCongestion))
    # print("----经过点的车流量----")
    # print(coveringCongestionList)
    # 计算经过所有区域的平均车流量
    averageCoveringCongestion = int(np.average(coveringCongestionList, axis=0))
    # print("----经过区域的平均车流量----")
    # print(averageCoveringCongestion)
    coefficient = congestionCoefficient(averageCoveringCongestion)
    # print("----拥堵系数----")
    # print("实际的系数是"+str(coefficient))
    return coefficient



if __name__ == "__main__":
    # 接受ID区域序列参数
    regionSeqStr=sys.argv[1].split('-')
    regionSeq=np.array(regionSeqStr).astype(np.int)
    seqLength=len(regionSeq)
    # print(regionSeq)
    # 设置最终输出系数矩阵格式
    coeff_matrix=np.zeros((seqLength,seqLength))

    # 系数矩阵
    for i in range(seqLength):
        for j in range(seqLength):
            coeff_matrix[i, j] = getCoefficientProcess(regionSeq[i], regionSeq[j])
    # print(coeff_matrix)

    for i in range(seqLength):
        oneLine=""
        for j in range(seqLength):
            if j!= seqLength-1:
                oneLine = oneLine + str(coeff_matrix[i, j]) + " "
            else:
                oneLine = oneLine + str(coeff_matrix[i, j])
        print(oneLine)



